Ext.namespace('FileManager');
Ext.namespace('FileManager.upload'); 

FileManager.upload.SWFUpload = function(config) {
    
    // setup some of swfupload settings
    this.settings = {};
    this.movieName = "SWFUpload_FileManager_" + SWFUpload.movieCount++;
    this.movieElement = null; 
    
    // Setup global control tracking
    SWFUpload.instances[this.movieName] = this;
    
    // upload related settings
    this.uploads = new Ext.util.MixedCollection(false, null);
    this.errors = new Ext.util.MixedCollection(false, null);
    
    // define the progress object
	this.pgInfo = {
	    totalFiles: 0,
	    doneFiles: 0,
		totalBytes: 0, 
		doneBytes: 0,
		lastBytes: 0,
		lastElapsed: 1,
		lastUpdate: null,
		timeElapsed: 1
	};
	this.uploadProgress = new FileManager.upload.UploadProgress({
	    prgObject: this.pgInfo
	});
	
	this.cycles = 0;
    
    FileManager.upload.SWFUpload.superclass.constructor.call(this, Ext.applyIf(config || {}, {    
        title: Plugin.messages["FileManager.upload.SWFUpload.title"],
        layout: 'anchor',     
        width: 480,
        height: 500,       
        border: false,
        resizable: false,
        maximizable: false,
        
        items: [{               
                height: 35,
                html: Plugin.messages["FileManager.upload.SWFUpload.tip"],
                cls: 'db-upload-header',
                border: false
                },
              new Ext.Panel({
                anchor: '100% -55',
                layout: 'border',
                border: true,
                
                tbar: [
                    {text: Plugin.messages["FileManager.upload.SWFUpload.tool.add"], iconCls:'db-icn-add', handler: this.browse, scope: this},
                    {text: Plugin.messages["FileManager.upload.SWFUpload.tool.start"], iconCls:'db-icn-play', handler: function(){ this.startUpload(); }, scope: this},
                    {text: Plugin.messages["FileManager.upload.SWFUpload.tool.stop"], iconCls:'db-icn-stop', handler: this.stopUpload, scope: this},
                    {text: Plugin.messages["FileManager.upload.SWFUpload.tool.cancel"], iconCls:'db-icn-cross', handler: this.cancelQueue, scope: this},
                    {text: Plugin.messages["FileManager.upload.SWFUpload.tool.clean"], iconCls:'db-icn-clear', handler: this.clearList, scope: this}
                ],
                
                items: [{
                    border: false,
                    region: 'north',
                    collapsed: false,
                    collapsible: true,
                    collapseMode: 'mini',
                    height: 95,                   
                    split: true,
                    layout: 'fit',
                    items: this.uploadProgress
                }, {                    
                    border: false,                    
                    region: 'center',
                    bodyStyle: 'position: relative;overflow-x: hidden;',
                    autoScroll: true,
                    cls: 'db-upload-files',
                    title: '<div class="name">'+Plugin.messages["FileManager.upload.SWFUpload.list.fileName"]+'</div><div class="size">'+Plugin.messages["FileManager.upload.SWFUpload.list.fileSize"]+'</div><div class="stat">&#160;</div>'
                }, {
                    border: false,
                    region: 'south',
                    collapsed: false,
                    collapsible: true,
                    collapseMode: 'mini',
                    height: 70,
                    bodyStyle: 'background-color:#000;color:#fff;padding-left:5px',                    
                    split: true,
                    autoScroll: true,
                    hidden: !config.debugEnabled
                }]                                        
            })
            ,{               
               height: 20,
                html: Plugin.messages["FileManager.upload.SWFUpload.switchMode"],
                cls: 'db-upload-footer',
                border: false
            }
        ],
        
        buttons: [
            {text:Plugin.messages["FileManager.common.close"], handler: this.close, scope:this}
        ]     
    
    }));    
    
    // Load the settings.  Load the Flash movie.
    this.initSettings();
    this.loadFlash();    
    
    // some event handlers for this window
    this.on('beforeclose', this.onBeforeClose, this);
    
    this.addEvents({
        'filecomplete' : true,
        'queuecomplete' : true,
        'switchclick' : true
    });
    
    // get switch link and hook to the click event    
    this.on('show', function() {
        this.items.items[2].body.first('span').on('click', this.onSwitchClick, this);
    }, this);

};

Ext.extend(FileManager.upload.SWFUpload, Ext.Window, {   

    initSettings : function() {

        this.settings["control_id"] = this.movieName;

        // UI setting
        this.settings["ui_function"] = null;
        this.settings["ui_container_id"] = "";
        this.settings["degraded_container_id"] = "";

        // Upload backend settings
        this.settings["upload_target_url"] = this.uploadUrl;
        this.settings["file_post_name"] = "Filedata";
        this.settings["post_params"] = {
        	sessionId: MyDesktop.currentSessionId,
        	folderId: this.folderId
        };

        // Flags
        this.settings["begin_upload_on_queue"] = false;
        this.settings["use_server_data_event"] = false;
        this.settings["validate_files"] = true;

        // File Settings
        this.settings["file_types"] = this.fileTypes || "*.*";
        this.settings["file_types_description"] = this.fileTypesDescription || "All Files";
        this.settings["file_size_limit"] = "2147482624";
        this.settings["file_upload_limit"] = "0";
        this.settings["file_queue_limit"] = "0";

        // Flash Settings
        this.settings["flash_url"] = this.flashUrl || "swfupload.swf";
        this.settings["flash_width"] = "1px";
        this.settings["flash_height"] = "1px";
        this.settings["flash_color"] = "#FFFFFF";

        // Debug Settings
        this.settings["debug_enabled"] = this.debugEnabled;
        this.debug_enabled = this.settings["debug_enabled"];
    },
    
    loadFlash : function() {
        var html, target_element, container;

        // Make sure an element with the ID we are going to use doesn't already exist
        if (document.getElementById(this.movieName) !== null) {
            return false;
        }

        // Get the body tag where we will be adding the flash movie
        target_element = document.getElementsByTagName("body")[0];
        if (typeof(target_element) === "undefined" || target_element === null) {
            this.debugMessage('Could not find an element to add the Flash too. Failed to find element for "flash_container_id" or the BODY element.');
            return false;
        }

        // Append the container and load the flash
        container = document.createElement("div");
        container.style.width = this.getSetting("flash_width");
        container.style.height = this.getSetting("flash_height");

        target_element.appendChild(container);
        container.innerHTML = this.getFlashHTML();  // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
    },    
    
    getFlashHTML : function() {
        var html = "";

        // Create Mozilla Embed HTML
        if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
            // Build the basic embed html
            html = '<embed type="application/x-shockwave-flash" src="' + this.getSetting("flash_url") + '" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '"';
            html += ' id="' + this.movieName + '" name="' + this.movieName + '" ';
            html += 'bgcolor="' + this.getSetting("flash_color") + '" quality="high" menu="false" flashvars="';

            html += this.getFlashVars();

            html += '" />';

            // Create IE Object HTML
        } else {

            // Build the basic Object tag
            html = '<object id="' + this.movieName + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '">';
            html += '<param name="movie" value="' + this.getSetting("flash_url") + '">';

            html += '<param name="bgcolor" value="' + this.getSetting("flash_color") + '" />';
            html += '<param name="quality" value="high" />';
            html += '<param name="menu" value="false" />';

            html += '<param name="flashvars" value="' + this.getFlashVars() + '" />';
            html += '</object>';
        }

        return html;
    },    
    
    getFlashVars : function () {
        // Add the cookies to the backend string
        var upload_target_url = this.getSetting("upload_target_url");
        var param_string = this.buildParamString();

        // Build the parameter string
        var html = "";
        html += "controlID=" + encodeURIComponent(this.getSetting("control_id"));
        html += "&uploadTargetURL=" + encodeURIComponent(upload_target_url);
        html += "&params=" + encodeURIComponent(param_string);
        html += "&filePostName=" + encodeURIComponent(this.getSetting("file_post_name"));
        html += "&beginUploadOnQueue=" + encodeURIComponent(this.getSetting("begin_upload_on_queue"));
        html += "&useServerDataEvent=" + encodeURIComponent(this.getSetting("use_server_data_event"));
        html += "&fileValidation=" + encodeURIComponent(this.getSetting("validate_files"));
        html += "&fileTypes=" + encodeURIComponent(this.getSetting("file_types"));
        html += "&fileTypesDescription=" + encodeURIComponent(this.getSetting("file_types_description"));
        html += "&fileSizeLimit=" + encodeURIComponent(this.getSetting("file_size_limit"));
        html += "&fileUploadLimit=" + encodeURIComponent(this.getSetting("file_upload_limit"));
        html += "&fileQueueLimit=" + encodeURIComponent(this.getSetting("file_queue_limit"));
        html += "&debugEnabled=" + encodeURIComponent(this.getSetting("debug_enabled"));

        return html;
    },  
    
    removeFlash : function() {
        var me = this.getMovieElement();
        
        // make sure that the movie exsits before we remove it from dom
        if (me !== null) {
            me.parentNode.removeChild(me);
        }
    },        
    
    getMovieElement : function () {
        if (typeof(this.movieElement) === "undefined" || this.movieElement === null) {
            this.movieElement = document.getElementById(this.movieName);
        }

        return this.movieElement;
    },      
    
    buildParamString : function () {
        var post_params = this.getSetting("post_params");
        var param_string_pairs = [];
        var i, value, name;

        // Retrieve the user defined parameters
        if (typeof(post_params) === "object") {
            for (name in post_params) {
                if (post_params.hasOwnProperty(name)) {
                    if (typeof(post_params[name]) === "string" /*&& upload_params[name] != ""*/) {
                        param_string_pairs.push(encodeURIComponent(name) + "=" + encodeURIComponent(post_params[name]));
                    }
                }
            }
        }

        return param_string_pairs.join("&");
    },   
    
    showUI : function () {
        var ui_container_id, ui_target, degraded_container_id, degraded_target;
        try {
            ui_container_id = this.getSetting("ui_container_id");

            if (ui_container_id !== "") {
                ui_target = document.getElementById(ui_container_id);
                if (ui_target !== null) {
                    ui_target.style.display = "block";

                    // Now that the UI has been taken care of hide the degraded UI
                    degraded_container_id = this.getSetting("degraded_container_id");
                    if (degraded_container_id !== "") {
                        degraded_target = document.getElementById(degraded_container_id);
                        if (degraded_target !== null) {
                            degraded_target.style.display = "none";
                        }
                    }
                }
            }

        } catch (ex) {
            this.debugMessage(ex);
        }
    },   
    
    getSetting : function (name) {
        if (typeof(this.settings[name]) === "undefined") {
            return "";
        } else {
            return this.settings[name];
        }
    },     
    
    /* -- Flash control methods -- */ 
    
    browse : function () {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.Browse) === "function") {
            try {
                movie_element.Browse();
            }
            catch (ex) {
                this.debugMessage("Could not call browse: " + ex);
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }

    }, 
    
    startUpload : function (file_id) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.StartUpload) === "function") {
            try {
                movie_element.StartUpload(file_id);
            }
            catch (ex) {
                this.debugMessage("Could not call StartUpload: " + ex);
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }
    },   
    
    cancelUpload : function (file_id) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.CancelUpload) === "function") {
            try {
                movie_element.CancelUpload(file_id);
            }
            catch (ex) {
                this.debugMessage("Could not call CancelUpload");
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }
    },
    
    cancelQueue : function () {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.CancelQueue) === "function") {
            try {
                movie_element.CancelQueue();
            }
            catch (ex) {
                this.debugMessage("Could not call CancelQueue");
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }

    },
    
    stopUpload : function () {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.StopUpload) === "function") {
            try {
                movie_element.StopUpload();
            }
            catch (ex) {
                this.debugMessage("Could not call StopUpload");
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }

    }, 
    
    addFileParam : function (file_id, name, value) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.AddFileParam) === "function") {
            try {
                return movie_element.AddFileParam(file_id, name, value);
            }
            catch (ex) {
                this.debugMessage("Could not call AddFileParam");
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }
    },

    removeFileParam : function (file_id, name) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.RemoveFileParam) === "function") {
            try {
                return movie_element.RemoveFileParam(file_id, name);
            }
            catch (ex) {
                this.debugMessage("Could not call AddFileParam");
            }
        } else {
            this.debugMessage("Could not find Flash element");
        }

    },

    setUploadTargetURL : function (url) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetUploadTargetURL) === "function") {
            try {
                this.addSetting("upload_target_url", url);
                movie_element.SetUploadTargetURL(this.getSetting("upload_target_url"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetUploadTargetURL");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetUploadTargetURL");
        }
    },

    setPostParams : function (param_object) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetPostParams) === "function") {
            try {
                this.addSetting("post_params", param_object);
                movie_element.SetPostParams(this.getSetting("post_params"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetPostParams");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetPostParams");
        }
    },

    setFileTypes : function (types, description) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetFileTypes) === "function") {
            try {
                this.addSetting("file_types", types);
                this.addSetting("file_types_description", description);
                movie_element.SetFileTypes(this.getSetting("file_types"), this.getSetting("file_types_description"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetFileTypes");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetFileTypes");
        }
    },

    setFileSizeLimit : function (file_size_limit) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetFileSizeLimit) === "function") {
            try {
                this.addSetting("file_size_limit", file_size_limit);
                movie_element.SetFileSizeLimit(this.getSetting("file_size_limit"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetFileSizeLimit");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetFileSizeLimit");
        }
    },

    setFileUploadLimit : function (file_upload_limit) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetFileUploadLimit) === "function") {
            try {
                this.addSetting("file_upload_limit", file_upload_limit);
                movie_element.SetFileUploadLimit(this.getSetting("file_upload_limit"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetFileUploadLimit");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetFileUploadLimit");
        }
    },

    setFileQueueLimit : function (file_queue_limit) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetFileQueueLimit) === "function") {
            try {
                this.addSetting("file_queue_limit", file_queue_limit);
                movie_element.SetFileQueueLimit(this.getSetting("file_queue_limit"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetFileQueueLimit");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetFileQueueLimit");
        }
    },

    setBeginUploadOnQueue : function (begin_upload_on_queue) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetBeginUploadOnQueue) === "function") {
            try {
                this.addSetting("begin_upload_on_queue", begin_upload_on_queue);
                movie_element.SetBeginUploadOnQueue(this.getSetting("begin_upload_on_queue"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetBeginUploadOnQueue");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetBeginUploadOnQueue");
        }
    },

    setUseServerDataEvent : function (use_server_data_event) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetUseServerDataEvent) === "function") {
            try {
                this.addSetting("use_server_data_event", use_server_data_event);
                movie_element.SetUseServerDataEvent(this.getSetting("use_server_data_event"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetUseServerDataEvent");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetUseServerDataEvent");
        }
    },

    setValidateFiles : function (validate_files) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetValidateFiles) === "function") {
            try {
                this.addSetting("validate_files", validate_files);
                movie_element.SetValidateFiles(this.getSetting("validate_files"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetValidateFiles");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetValidateFiles");
        }
    },

    setFilePostName : function (file_post_name) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetFilePostName) === "function") {
            try {
                this.addSetting("file_post_name", file_post_name);
                movie_element.SetFilePostName(this.getSetting("file_post_name"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetFilePostName");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetFilePostName");
        }
    },

    setDebugEnabled : function (debug_enabled) {
        var movie_element = this.getMovieElement();
        if (movie_element !== null && typeof(movie_element.SetDebugEnabled) === "function") {
            try {
                this.addSetting("debug_enabled", debug_enabled);
                this.debug_enabled = this.getSetting("debug_enabled");
                movie_element.SetDebugEnabled(this.getSetting("debug_enabled"));
            }
            catch (ex) {
                this.debugMessage("Could not call SetDebugEnabled");
            }
        } else {
            this.debugMessage("Could not find Flash element in SetDebugEnabled");
        }
    },
    
    /* -- Event Handlers -- */
    
    flashReady : function () {
        var ui_function;
        try {
            this.debugMessage("Flash called back and is ready.");

            ui_function = this.getSetting("ui_function");
            if (typeof(ui_function) === "function") {
                ui_function.apply(this);
            } else {
                this.showUI();
            }
        } catch (ex) {
            this.debugMessage(ex);
        }
    },

    dialogCancelled : function () {
        this.debugMessage("browse Dialog Cancelled.");
    },

    fileQueued : function (file) {            
        
        var error = null;
        
        // validate file
        if (file.size > this.fileSize) {
            error = Plugin.messages["FileManager.upload.SWFUpload.error.sizeExceeded"].replace("{1}",Ext.util.Format.ellipsis(file.name, 36));
        } else if (this.pgInfo.totalBytes + file.size > this.storageLeft) {
            error = Plugin.messages["FileManager.upload.SWFUpload.error.storageExceeded"].replace("{1}",Ext.util.Format.ellipsis(file.name, 38));
        } else if (this.pgInfo.totalBytes + file.size > this.bandwidthLeft) {
            error = Plugin.messages["FileManager.upload.SWFUpload.error.bandwidthExceeded"].replace("{1}",Ext.util.Format.ellipsis(file.name, 36));
        }
        
        if(error) {
            this.cancelUpload(file.id)
            var ue = new FileManager.upload.UploadError({
                error: error
            });
            this.addFileProgress(ue);   
            this.errors.add(file.id, ue);
            
            this.debugMessage("File Queue Error: " + error);             
        } else {
            var fp = new FileManager.upload.FileProgress({
                fileName : file.name,
                fileSize : file.size
            });
            fp.on('cancel', function(){ this.cancelUpload(file.id); }, this);
            this.uploads.add(file.id, fp);
            this.addFileProgress(fp);
            
            // update progress info
            this.pgInfo.totalFiles += 1;
            this.pgInfo.totalBytes += file.size;
            this.updateProgressInfo(); 
            
            this.debugMessage("File Queued: " + file.id);       
        }
    },

    fileValidation : function (file) {
        this.debugMessage("File Validation: " + file.id);   
        
        // scroll file into view 
        var c = this.items.items[1].items.items[1].body;
        if (c.isScrollable())
        {
            var el = this.uploads.get(file.id).getEl();
            
            var t = el.getTop() - c.getTop(),
                b = t + el.getHeight(),
                ch = c.getHeight();
            
            if(t < 0){
    	        c.scroll('t', -1*t, true);
            }else if(b > ch){
                c.scroll('b', b-ch+el.getHeight(), true);
            }        
        }
        
        return true;
    },

    fileProgress : function (file, bytes_complete) {
        var fp = this.uploads.get(file.id);
        var bytes_added = bytes_complete - fp.getBytesCompleted();
        fp.setProgress(bytes_complete);
        
        // update progress info
        this.pgInfo.doneBytes += bytes_added;
        if (this.pgInfo.lastUpdate) {
            this.pgInfo.lastElapsed = this.pgInfo.lastUpdate.getElapsed();
            this.pgInfo.timeElapsed += this.pgInfo.lastElapsed;
        }
        this.pgInfo.lastBytes = bytes_added;
        this.pgInfo.lastUpdate = new Date();        
        this.updateProgressInfo();  
        
        this.cycles++;      
        
        this.debugMessage("File Progress: " + file.id + ", Bytes: " + bytes_complete);
    },

    fileCancelled : function (file) {
        this.uploads.get(file.id).setCancelled();
        
        // update progress info
        this.pgInfo.totalFiles -= 1;
        this.pgInfo.totalBytes -= file.size;
        this.pgInfo.doneBytes -= this.uploads.get(file.id).getBytesCompleted();
        this.updateProgressInfo();        
        
        this.debugMessage("File Cancelled: " + file.id);
    },

    fileComplete : function (file, server_data) {
        this.uploads.get(file.id).setComplete();
        
        // update progress info
        this.pgInfo.doneFiles += 1;
        this.updateProgressInfo(); 
        
        // fire event
        this.fireEvent('filecomplete', this, file, this.folderId);
        
        this.debugMessage("File Complete: " + file.id);
        if (typeof(server_data) !== "undefined") {
            this.debugMessage("Upload Response Data: " + server_data);
        }
    },

    queueComplete : function (file_upload_count) {
        
        // update progress Info
        this.pgInfo.lastUpdate = null;
        
        // fire event
        this.fireEvent('queuecomplete', this, this.folderId);        
        
        this.debugMessage("Queue Complete. Files Uploaded:" + file_upload_count);
    },

    queueStopped : function (file) {

        // update progress Info
        this.pgInfo.lastUpdate = null;
        this.pgInfo.doneBytes -= this.uploads.get(file.id).getBytesCompleted();
        this.updateProgressInfo();       
        
        // reset file progress
        this.uploads.get(file.id).setProgress(0);
        
        this.debugMessage("Queue Stopped. File Stopped:" + file.id);
    },

    debug : function (message) {
        this.debugMessage(message);
    },

    error : function (errcode, file, msg) {
        // update progress info
        if (file) {
            this.uploads.get(file.id).setError();
            
            this.pgInfo.totalFiles -= 1;
            this.pgInfo.totalBytes -= file.size;
            this.pgInfo.doneBytes -= this.uploads.get(file.id).getBytesCompleted();
            this.updateProgressInfo();              
        }
        
        try {
            switch (errcode) {
            case FileManager.upload.SWFUpload.ERROR_CODE_HTTP_ERROR:
                this.debugMessage("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_MISSING_UPLOAD_TARGET:
                this.debugMessage("Error Code: No backend file, File name: " + file.name + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_IO_ERROR:
                this.debugMessage("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_SECURITY_ERROR:
                this.debugMessage("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT:
                this.debugMessage("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_ZERO_BYTE_FILE:
                this.debugMessage("Error Code: Zero Byte File, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED:
                this.debugMessage("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_QUEUE_LIMIT_EXCEEDED:
                this.debugMessage("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_UPLOAD_FAILED:
                this.debugMessage("Error Code: Upload Initialization exception, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_SPECIFIED_FILE_NOT_FOUND:
                this.debugMessage("Error Code: File ID specified for upload was not found, Message: " + msg);
                break;
            case FileManager.upload.SWFUpload.ERROR_CODE_INVALID_FILETYPE:
                this.debugMessage("Error Code: File extension is not allowed, Message: " + msg);
                break;
            default:
                this.debugMessage("Error Code: Unhandled error occured. Errorcode: " + errcode);
            }
        } catch (ex) {
            this.debugMessage(ex);
        }
    },
    
    debugMessage : function (message) {
        var exception_message, exception_values;
        //this.writeMessage(message);
        if (this.debug_enabled) {
            if (typeof(message) === "object" && typeof(message.name) === "string" && typeof(message.message) === "string") {
                exception_message = "";
                exception_values = [];
                for (var key in message) {
                    exception_values.push(key + ": " + message[key]);
                }
                exception_message = exception_values.join("<br />");
                exception_values = exception_message.split("<br />");
                exception_message = "EXCEPTION: " + exception_values.join("<br />EXCEPTION: ");
                this.writeMessage(exception_message);
            } else {
                this.writeMessage(message);
            }
        }
    },
    
    writeMessage : function(msg) {      
        var console = this.items.items[1].items.items[2].body.dom;
        if (console) {
            console.innerHTML += '<div style="white-space:nowrap">' + msg + '</div>';
            console.scrollTop = console.scrollHeight - console.clientHeight;
        }
    },

    addFileProgress : function(fp) {   
        this.items.items[1].items.items[1].add(fp);
        this.doLayout();
    },
    
    updateProgressInfo: function() {
        this.uploadProgress.updateProgress(this.pgInfo);
    },
    
    clearList : function() {                
        // clear completed uploads
        this.uploads.each(function(u) {
            u.clear();
        });
        
        // clear errors
        this.errors.each(function(u) {
            u.clear();
        });        
    },
    
    onBeforeClose: function(wnd) {
        var cnt = 0;
        this.uploads.each(function(u) {
            if (!u.done())
                cnt++;
        });
        if(cnt === 0) {
            this.removeFlash();
            return true;
        }
            
        Ext.Msg.show({
            title:"Close upload dialog?",
            msg: "There are still " + cnt + " files in the queue. Are you sure you want to cancel these uploads?",
            buttons: Ext.Msg.YESNO,           
            icon: Ext.MessageBox.QUESTION,
            modal: false,
            scope: this,
            fn: function(btn) {
                if(btn == 'yes') {
                    this.cancelQueue(); 
                    this.close();
                }
            }
        });

        return false;
    },
    
    onSwitchClick: function() {
        this.fireEvent('switchclick', this);
        return false;
    }
    
});

SWFUpload = function() {};
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
FileManager.upload.SWFUpload.ERROR_CODE_HTTP_ERROR               = -10;
FileManager.upload.SWFUpload.ERROR_CODE_MISSING_UPLOAD_TARGET    = -20;
FileManager.upload.SWFUpload.ERROR_CODE_IO_ERROR                 = -30;
FileManager.upload.SWFUpload.ERROR_CODE_SECURITY_ERROR           = -40;
FileManager.upload.SWFUpload.ERROR_CODE_FILE_EXCEEDS_SIZE_LIMIT  = -50;
FileManager.upload.SWFUpload.ERROR_CODE_ZERO_BYTE_FILE           = -60;
FileManager.upload.SWFUpload.ERROR_CODE_UPLOAD_LIMIT_EXCEEDED    = -70;
FileManager.upload.SWFUpload.ERROR_CODE_UPLOAD_FAILED            = -80;
FileManager.upload.SWFUpload.ERROR_CODE_QUEUE_LIMIT_EXCEEDED     = -90;
FileManager.upload.SWFUpload.ERROR_CODE_SPECIFIED_FILE_NOT_FOUND = -100;
FileManager.upload.SWFUpload.ERROR_CODE_INVALID_FILETYPE         = -110;


FileManager.upload.FileProgress = Ext.extend(Ext.BoxComponent, {

    baseCls : 'db-file-progress',

    // private
    initComponent : function(){
        FileManager.upload.FileProgress.superclass.initComponent.call(this);
        this.addEvents({
            "cancel" : true
        });
    },

    // private
    onRender : function(ct, position){
        FileManager.upload.FileProgress.superclass.onRender.call(this, ct, position);

        var tpl = new Ext.Template(
            '<div class="{cls}-wrap">',
                '<div class="{cls}-wbar">',
                    '<div class="{cls}-bar">&#160;</div>',
                '</div>',    
                '<div class="{cls}-text">',
                    '<div class="name">&#160;</div>',
                    '<div class="size">&#160;</div>',
                    '<div class="stat">',
                        '<span class="cancel">&#160;</span>',
                    '</div>',
                '</div>',
            '</div>'
        );

        if(position){
            this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
        }else{
            this.el = tpl.append(ct, {cls: this.baseCls}, true);
        }
        if(this.id){
            this.el.dom.id = this.id;
        }
        
        //setup our progress bar elem
        var wbar = this.el.dom.firstChild;
        this.progressBar = Ext.get(wbar.firstChild);
        this.progressBar.setWidth(0);
        this.progressBar.setVisible(true);        
        this.progressBar.setHeight(wbar.offsetHeight);

        //setup our internal layered text els
        var textEl = this.el.dom.childNodes[1];   
        this.textNameEl = Ext.get(textEl.firstChild);
        this.textSizeEl = Ext.get(textEl.childNodes[1]);
        this.textStatEl = Ext.get(textEl.childNodes[2]);
        this.linkCancelEl = Ext.get(this.textStatEl.dom.firstChild);
        
        this.linkCancelEl.on('click', this.onCancel, this);

        if(this.fileName || this.fileSize){
            this.setText(this.fileName, this.fileSize);
        }
        this.setSize(this.width || 'auto', 'auto');
    },
    
    setText : function(fileName, fileSize){
        this.fileName = fileName || '&#160;';
        this.fileSize = fileSize || '&#160;';
        this.textNameEl.update(this.fileName);
        this.textSizeEl.update(Ext.util.Format.fileSize(this.fileSize));
        return this;
    },   
    
    setProgress : function(bytesComplete){
        this.bytesComplete = bytesComplete || 0;
        var percentage = Math.ceil((bytesComplete / this.fileSize) * 100)
        
        var w = Math.floor(percentage*this.el.dom.firstChild.offsetWidth/100);
        this.progressBar.removeClass('x-hidden').setWidth(w, true);
        
        return this;
    },   
    
    setComplete : function() {
        this.el.addClass(this.baseCls+'-complete');
        this.progressBar.hide(true);
        this.progressComplete = true;
        return this;
    },
    
    setError : function() {
        this.el.addClass(this.baseCls+'-error');
        this.progressBar.hide();
        this.progressError = true;
        return this;
    },
    
    setCancelled : function() {
        this.el.addClass(this.baseCls+'-cancel');
        this.progressBar.hide();
        this.progressCancel = true;
        return this;
    },
    
    getFileName : function() {
        return this.fileName || '';
    },
    
    getFileSize : function() {
        return this.fileSize || 0;
    },
    
    getBytesCompleted : function() {
        return this.bytesComplete || 0;
    },
    
    onCancel : function() {
        this.fireEvent('cancel', this, this.percentage);
    },
    
    clear: function() {
        if (this.done()) {
            this.hide();
        }
    },
    
    done: function() {
        return this.progressComplete || this.progressError || this.progressCancel;
    }
});

FileManager.upload.UploadError = Ext.extend(Ext.BoxComponent, {

    baseCls : 'db-upload-error',

    // private
    initComponent : function(){
        FileManager.upload.UploadError.superclass.initComponent.call(this);
    },

    // private
    onRender : function(ct, position){
        FileManager.upload.UploadError.superclass.onRender.call(this, ct, position);

        var tpl = new Ext.Template(
            '<div class="{cls}-wrap">',    
                '<div class="{cls}-text">',
                    '<div class="name">&#160;</div>',
                    '<div class="cancel">',
                        '<span class="close">&#160;</span>',
                    '</div>',
                '</div>',
            '</div>'
        );

        if(position){
            this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
        }else{
            this.el = tpl.append(ct, {cls: this.baseCls}, true);
        }
        if(this.id){
            this.el.dom.id = this.id;
        }

        //setup our internal layered text els
        var textEl = this.el.dom.firstChild;   
        this.textErrorEl = Ext.get(textEl.firstChild);
        this.textCancelEl = Ext.get(textEl.childNodes[1]);
        this.linkCloseEl = Ext.get(this.textCancelEl.dom.firstChild);
        
        this.linkCloseEl.on('click', this.onClose, this);

        if(this.error){
            this.setError(this.error);
        }
    },
    
    setError: function(error){
        this.error = error || 'Error!';
        this.textErrorEl.update(this.error);
        return this;
    },
    
    onClose : function() {
        this.hide();
    },
    
    clear : function() {
        this.hide();
    }
});

FileManager.upload.UploadProgress = Ext.extend(Ext.BoxComponent, {

    baseCls : 'db-upload-progress',

    // private
    initComponent : function(){
        FileManager.upload.FileProgress.superclass.initComponent.call(this);
        this.addEvents({
            "update" : true
        });
    },

    // private
    onRender : function(ct, position){
        FileManager.upload.FileProgress.superclass.onRender.call(this, ct, position);

        var tpl = new Ext.Template(
            '<div class="{cls}-wrap">',
                '<div class="{cls}-bar"></div>',
                '<div class="{cls}-text"></div>',
            '</div>'
        );

        if(position){
            this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
        }else{
            this.el = tpl.append(ct, {cls: this.baseCls}, true);
        }
        if(this.id){
            this.el.dom.id = this.id;
        }
        
        //setup our progress bar elem
        var bar = this.el.dom.firstChild;
        this.progressBar = new Ext.ProgressBar({
            renderTo: bar,
            text: Plugin.messages["FileManager.upload.SWFUpload.progress.uploading"] + ' 0%'
        });
        
        // setup text part of the progress
        var text = this.el.dom.childNodes[1];
        this.textEl = Ext.get(text);
        
        // setup progress template
        this.tpl = this.getProgressTemplate();
        
        // check if we should update progress right away
        if(this.prgObject) {
            this.updateProgress(this.prgObject);
        }
    },
    
    updateProgress : function(prgObject){
        this.prgObject = prgObject;
        
        this.textEl.update(this.tpl.apply(this.formatProgress(prgObject)));
    },
    
    formatProgress : function(prgObject) {
        var ro = {};
        ro.files_uploaded = String.leftPad(prgObject.doneFiles, 3, '&nbsp;');
        ro.files_total = prgObject.totalFiles;
        ro.bytes_uploaded = String.leftPad(Ext.util.Format.fileSize(prgObject.doneBytes), 13, '&#160;');
        ro.bytes_total = Ext.util.Format.fileSize(prgObject.totalBytes);
        ro.time_elapsed = this.formatTime(prgObject.timeElapsed);
        ro.speed_average = Ext.util.Format.fileSize(1000*prgObject.doneBytes/prgObject.timeElapsed)+'/s';
        ro.time_left = this.formatTime((prgObject.doneBytes === 0)? 0 : prgObject.timeElapsed*(prgObject.totalBytes - prgObject.doneBytes)/prgObject.doneBytes);
        ro.speed_last = Ext.util.Format.fileSize(1000*prgObject.lastBytes/prgObject.lastElapsed)+'/s';
        
        // update progressbar
        var pr = prgObject.doneBytes/prgObject.totalBytes;
        pr = pr || 0;
        this.progressBar.updateProgress(pr, Plugin.messages["FileManager.upload.SWFUpload.progress.uploading"] + " " + parseInt(pr*100) + "%");
        return ro;
    },
    
    formatTime: function(milliseconds) {
        var seconds = parseInt(milliseconds/1000, 10);
		var s = 0;
		var m = 0;
		var h = 0;
		if(3599 < seconds) {
			h = parseInt(seconds/3600, 10);
			seconds -= h * 3600;
		}
		if(59 < seconds) {
			m = parseInt(seconds/60, 10);
			seconds -= m * 60;
		}
		
		m = String.leftPad(m, 2, 0);
		h = String.leftPad(h, 2, 0);
		s = String.leftPad(seconds, 2, 0);
		
		return h + ':' + m + ':' + s;
	},    
    
    getProgressTemplate: function() {
		var tpl = new Ext.Template(
				'<table class="db-upload-progress-table"><tbody>',
				'<tr><td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.fileUploaded"]+':</td>',
				'<td class="db-upload-progress-value">{files_uploaded} of {files_total}</td>',
				'<td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.uploadStatus"]+':</td>',
				'<td class="db-upload-progress-value">{bytes_uploaded} of {bytes_total}</td></tr>',				
                '<tr><td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.elapsedTime"]+':</td>',
				'<td class="db-upload-progress-value">{time_elapsed}</td>',
                '<td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.timeLeft"]+':</td>',
				'<td class="db-upload-progress-value">{time_left}</td></tr>',
                '<tr><td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.currentSpeed"]+':</td>',
				'<td class="db-upload-progress-value">{speed_last}</td>',
                '<td class="db-upload-progress-label">'+Plugin.messages["FileManager.upload.SWFUpload.progress.averageSpeed"]+':</td>',
				'<td class="db-upload-progress-value">{speed_average}</td></tr>',										
				'</tbody></table>'
		);
		tpl.compile();
		return tpl;
    }    
});

FileManager.HTMLComponent = Ext.extend(Ext.BoxComponent, {

    baseCls : 'db-html',

    // private
    onRender : function(ct, position){
        FileManager.HTMLComponent.superclass.onRender.call(this, ct, position);

        var tpl = new Ext.Template(
            '<div class="{cls}">',
            '</div>'
        );

        if(position){
            this.el = tpl.insertBefore(position, {cls: this.baseCls}, true);
        }else{
            this.el = tpl.append(ct, {cls: this.baseCls}, true);
        }
        if(this.id){
            this.el.dom.id = this.id;
        }
        
        if(this.html){
            this.setHTML(this.html);
        }
    },
    
    setHTML: function(html){
        this.html = html || '';
        this.el.update(this.html);
        return this;
    }
});